package books;

import java.util.ArrayList;
import java.util.List;

import util.Entity;
import builders.BookInfoHomeBuilder;
import exceptions.CopyIdAlreadyExistsException;
import exceptions.NoCopyAvailableException;
import exceptions.NotABorrowedCopyException;

/**
 * Manages the copies of a specific BookInfo.
 */
public class BookInfoHome extends Entity {

    private static final long serialVersionUID = 1L;

    private BookInfo bookInfo;

    private List<Book> availableCopies;

    private List<Book> borrowedCopies;

    private int timesBorrowed;

    public BookInfoHome(final BookInfo aBookInfo) {
        super();
        this.bookInfo = aBookInfo;
        this.availableCopies = new ArrayList<Book>();
        this.borrowedCopies = new ArrayList<Book>();
        this.timesBorrowed = 0;
    }

    public BookInfoHome() {
        // empty constructor
        super();
        this.availableCopies = new ArrayList<Book>();
        this.borrowedCopies = new ArrayList<Book>();
        this.timesBorrowed = 0;
    }

    public BookInfoHome(final BookInfoHomeBuilder builder) {
        super();
        this.availableCopies = builder.getAvailableCopies();
        this.borrowedCopies = builder.getBorrowedCopies();
        this.bookInfo = builder.getBookInfo();
        this.timesBorrowed = builder.getTimesBorrowed();
    }

    // --------------- ACCESSORS --------------------------
    public List<Book> getAvailableCopies() {
        return this.availableCopies;
    }

    public void setAvailableCopies(final List<Book> availableCopies) {
        this.availableCopies = availableCopies;
    }

    public List<Book> getBorrowedCopies() {
        return this.borrowedCopies;
    }

    public void setBorrowedCopies(final List<Book> borrowedCopies) {
        this.borrowedCopies = borrowedCopies;
    }

    public void setTimesBorrowed(final int timesBorrowed) {
        this.timesBorrowed = timesBorrowed;
    }

    public int getTimesBorrowed() {
        return this.timesBorrowed;
    }

    // ------------------------------------------------------

    public void addNewCopy(final Book aCopy) {
        this.validateNewCopy(aCopy);
        this.getAvailableCopies().add(aCopy);
    }

    public void validateNewCopy(final Book aCopy) {

        if (this.getAllCopies().contains(aCopy)) {
            throw new CopyIdAlreadyExistsException();
        }
    }

    public void returnCopy(final Book aCopy) {
        this.validateReturnedCopy(aCopy);
        this.getBorrowedCopies().remove(aCopy);
        this.getAvailableCopies().add(aCopy);
    }

    public void validateReturnedCopy(final Book aCopy) {
        if (!this.getBorrowedCopies().contains(aCopy)) {
            throw new NotABorrowedCopyException();
        }
    }

    public Book borrowACopy() {
        this.validateBorrowCopy();
        Book copy = this.getAvailableCopies().remove(0);
        this.getBorrowedCopies().add(copy);

        // increase the total times a copy was burrowed
        this.setTimesBorrowed(this.getTimesBorrowed() + 1);

        return copy;
    }

    public void validateBorrowCopy() {
        if (this.getAvailableCopies().isEmpty()) {
            throw new NoCopyAvailableException();
        }
    }

    public List<Book> getAllCopies() {
        List<Book> copies = new ArrayList<Book>();
        copies.addAll(this.getAvailableCopies());
        copies.addAll(this.getBorrowedCopies());

        return copies;
    }

    // ------------//

    public int getAmmountOfCopies() {
        int ret = 0;

        for (Book it : this.getAllCopies()) {
            // I dont like this check...
            if (it.getInfo().getIsbn().equals(this.getAllCopies().get(0).getInfo().getIsbn())) {
                ret++;
            }
        }

        return ret;
    }

    public void setBookInfo(final BookInfo bookInfo) {
        this.bookInfo = bookInfo;
    }

    public BookInfo getBookInfo() {
        return this.bookInfo;
    }

    public boolean areAvailableCopies() {
        return !this.getAvailableCopies().isEmpty();
    }
}
